/**
 * 
 */
package br.com.skynix.tcmc.base.excecao;

import java.util.Iterator;

import javax.faces.FacesException;
import javax.faces.application.FacesMessage;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerWrapper;
import javax.faces.context.FacesContext;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;

import org.apache.commons.lang3.StringUtils;

import br.com.skynix.tcmc.util.WebUtil;

/**
 * @author mgrb
 * 
 */
public class SkynixExceptionHandlerWrapper extends ExceptionHandlerWrapper {

	private ExceptionHandler wrapper;

	/**
	 * 
	 */
	public SkynixExceptionHandlerWrapper(ExceptionHandler wrapper) {
		this.wrapper = wrapper;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.faces.context.ExceptionHandlerWrapper#getWrapped()
	 */
	@Override
	public ExceptionHandler getWrapped() {
		return wrapper;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see javax.faces.context.ExceptionHandlerWrapper#handle()
	 */
	@Override
	public void handle() throws FacesException {
		// Iterate over all unhandeled exceptions
		Iterator<ExceptionQueuedEvent> i = getUnhandledExceptionQueuedEvents()
				.iterator();
		while (i.hasNext()) {
			ExceptionQueuedEvent event = i.next();
			ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event
					.getSource();

			// obtain throwable object
			Throwable t = context.getException();

			// here you do what ever you want with exception
			try {
				Throwable rootCause = getOrigeCause(t);
				if (NegocioException.class.equals(rootCause.getClass())) {
					tratarNegocioException((NegocioException) rootCause);
				}
				else {
					tratarExcecao(rootCause);
				}
			}
			finally {
				// after exception is handeled, remove it from queue
				i.remove();
			}
		}
		// let the parent handle the rest
		getWrapped().handle();
	}

	/**
	 * @param rootCause
	 * 
	 */
	private void tratarNegocioException(NegocioException rootCause) {
		for (MensagemErro erroMsg : rootCause.getErros()) {
			String msg = WebUtil.getMensage(erroMsg.getErrorMsgKey());
			if (StringUtils.isNotBlank(msg)) {
				for (int i = 0; i < erroMsg.getParametrosSize(); i++) {
					String param = erroMsg.getParametros()[i];
					param = WebUtil.getLabel(param);
					if (StringUtils.isBlank(param)) {
						param = erroMsg.getParametros()[i];
					}
					msg = msg.replace("{" + i + "}", param);
				}
			}
			FacesContext.getCurrentInstance().addMessage(null,
					new FacesMessage(FacesMessage.SEVERITY_ERROR, msg, ""));
			System.out.println("Serious error happened!" + msg);

		}
	}

	/**
	 * @param t
	 * @param rootCause
	 */
	private void tratarExcecao(Throwable rootCause) {
		rootCause = getOrigeCause(rootCause);
		FacesContext.getCurrentInstance().addMessage(
				null,
				new FacesMessage(FacesMessage.SEVERITY_ERROR, rootCause
						.getClass().getSimpleName(), rootCause.getMessage()));
		// log error
		System.out.println("Serious error happened!" + rootCause.getMessage());
		// redirect to error view etc....
	}

	/**
	 * @param rootCause
	 * @return
	 */
	private Throwable getOrigeCause(Throwable rootCause) {
		while (rootCause.getCause() != null) {
			rootCause = rootCause.getCause();
		}
		return rootCause;
	}

}
